/*
 * Copyright 2011, 2012 Fabian Wenzelmann
 * 
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 * 
 * Recognition-Procedures-for-Boolean-Functions is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.wenzelmf.booleanFunction.lpb.combinatorial.splittingTree;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;

import de.wenzelmf.booleanFunction.dnf.Clause;
import de.wenzelmf.booleanFunction.dnf.DNF;
import de.wenzelmf.booleanFunction.dnf.Literal;
import de.wenzelmf.booleanFunction.lpb.combinatorial.occurrencePattern.OccurrencePattern;
import de.wenzelmf.booleanFunction.lpb.combinatorial.occurrencePattern.OccurrencePatternFactory;
import de.wenzelmf.booleanFunction.lpb.util.LPBCombinatorialConstants;

/**
 * A special main node in the splitting tree that is used as root of the tree.
 * 
 * A start node does not have parent nodes and the occurrence patterns have to be created
 * from the initial DNF:
 * 
 * @author Fabian Wenzelmann
 * @version 1.0
 *
 */
public class StartNode extends MainNode
{
	
	/**
	 * Construct a new start node.
	 * 
	 * The occurrence patterns are not automatically initialized, this will be done when the
	 * {@link #getSetting(OccurrencePatternFactory)} method is called.
	 * 
	 * @param dnf The DNF associated with this node.
	 * @param context Information about the tree this node is used in.
	 */
	public StartNode(DNF dnf, TreeContext context)
	{
		super(null, null, dnf, null, context);
	}
	
	/**
	 * Constructs the initial variable setting, i.e. creates all occurrence patterns of this DNF
	 * and sorts them.
	 * 
	 * Also initializes the occurrence patterns field of this node, which is null before.
	 * 
	 * @param factory The factory that is used to create the occurrence patterns.
	 * 
	 * @return The initial variable setting.
	 */
	public VariableSetting getSetting(OccurrencePatternFactory factory)
	{
		// create all occurrence pattern for this dnf
		HashMap<String, OccurrencePattern> patternMap = new HashMap<String, OccurrencePattern>();
		
		for(Clause c : dnf)
		{
			for(Literal l : c)
			{
				String name = l.getIdentifier();
				OccurrencePattern pattern = patternMap.get(name);
				if(pattern == null)
				{
					pattern = factory.getEmptyInstance(name);
					patternMap.put(name, pattern);
				}
				pattern.addOccurrence(c.size());
			}
		}
		
		OccurrencePattern[] patterns = new OccurrencePattern[patternMap.size()];
		patterns = patternMap.values().toArray(patterns);
		/*int pos = 0;
		for(OccurrencePattern p : patternMap.values())
		{
			patterns[pos++] = p;
		}
		*/
		Comparator<OccurrencePattern> comp = new Comparator<OccurrencePattern>()
		{

			@Override
			public int compare(OccurrencePattern arg0, OccurrencePattern arg1)
			{
				return -arg0.compareTo(arg1);
			}
			
		};
		Arrays.sort(patterns, comp);
		this.occurrencePatterns = patterns;
		
		return new VariableSetting(patterns);
	}

	/**
	 * Constructs the initial variable setting, i.e. creates all occurrence patterns of this DNF
	 * and sorts them.
	 * 
	 * Also initializes the occurrence patterns field of this node, which is null before.
	 * 
	 * It just calls {@link #getSetting(OccurrencePatternFactory)} with the default occurrence
	 * pattern factory as defined in {@link LPBCombinatorialConstants}.
	 * 
	 * @return The initial variable setting.
	 * 
	 * @see #getSetting(OccurrencePatternFactory)
	 */
	public VariableSetting getSetting()
	{
		return getSetting(LPBCombinatorialConstants.defaultOPFactory);
	}
	
	/**
	 * Create a String representation of this node.
	 * 
	 * @return "Start Node: " + dnf.toString().
	 */
	@Override
	public String toString()
	{
		return "Start Node: " + dnf;
	}
	
	/**
	 * Returns the type of the node, that is "startNode".
	 * 
	 * @return "startNode".
	 */
	@Override
	public String getType()
	{
		return "startNode";
	}
	
}
